#include <deftype.h>
#include <regs.h>
#include <system.h>


#define BaudRate 115200/*波特率*/

/***************串口初始化函数***************************
 *波特率为：115200
 *8个数据位
 *一个停止位
 *无奇偶校验
 *无硬件数据流控制
 */
void USART1_Init(void){
	uint32 tmpreg = 0;
	uint32 IntegerDivider = 0;
	uint32 FractionalDivider = 0;
	
	/*****初始化GPIO_A*****/
	/*使能GPIO_A时钟*/
	RCC_APB2ENR |= (uint32)0x00000004;
	/*配置PA9为复用推挽输出，频率50MHz*/
	GPIOA_CRH &= (uint32)0xffffff0f;
	GPIOA_CRH |= (uint32)0x000000b0;
	/*配置PA10为浮空输入*/
	GPIOA_CRH &= (uint32)0xfffff0ff;
	GPIOA_CRH |= (uint32)0x00000400;
	/*****初始化USART*****/
	/*设置RCC_APB2ENR寄存器，使能USART1时钟*/
	RCC_APB2ENR |= (uint32)0x00004000;
	/****波特率设置****
	 *公式：波特率=fck/（16*USARTDIV）
	 *fCK是给外设的时钟(PCLK1用于USART2、3、4、5，PCLK2用于USART1)
	 *例如我们设置波特率115200，已知fck=pclk2=72000000，求得USARTDIV=39.0625
	 *所以USART_BRR寄存器的整数部分写入39（0x27<<4）
	 *求小数部分写入值，0.0625*16=1，所以小数部分写入1
	 *假如USARTDIV求得25.62或50.99，小数部分计算16*0.62 = 9.92或16*0.99 = 15.84
	 *第一个四舍五入后为10（0xA）,写入USART_BRR寄存器[3:0]
	 *第二个四舍五入后为16（0x10），写入USART_BRR[3:0]寄存器会溢出
	 *所以需要进位，USART_BRR[15:4] = 整数部分(50.990 + 进位) = 51（0x33<<4） 
	 *USART_BRR[3:0]小数部分写0
	 */
	/*寄存器USART_BRR[15:4]：USARTDIV的整数部分计算*/
	/*相当于(PCLK2 / (16 * BaudRate))*100,求得3906的整数，数据放大100倍，39是整数部分，06是小数部分*/
	IntegerDivider = ((25 * PCLK2) / (4 * BaudRate));
	tmpreg = (IntegerDivider / 100) << 4;
	/*寄存器USART_BRR[3:0]：USARTDIV的小数部分计算*/
	/*3906-(100*39)=06*/
	FractionalDivider = IntegerDivider - (100 * (tmpreg >> 4));
	/*乘以16求小数部分的值*/
	/*加50用于四舍五入求近似值*/
	/*由于数据放大了100倍，需要除以100*/
	/*((6*16)+50)/100=1.46,丢弃0.46，所以寄存器USART_BRR[3:0]写入1*/
	tmpreg |= ((((FractionalDivider * 16) + 50) / 100)) & ((uint8)0x0f); 
	/*用tmpreg值设置寄存器USART_BRR*/
	USART_BRR = (uint16)tmpreg;
	/******定义了数据字的长度：一个起始位，8个数据位******/
	USART_CR1 &= (uint16)(~(0x1000));
	/*设置停止位*/
	USART_CR2 &= (uint16)(~(0x3000));
	/*设置为无奇偶校验位*/
	USART_CR1 &= (uint16)(~(0x0400));
	/*无硬件数据流控制*/
	USART_CR3 &= (uint16)(~(0x0300));
	/*收发模式使能*/
	USART_CR1 &= (uint16)(~(0x000c));
	USART_CR1 |= (uint16)0x000c;
	/*使能USART1*/
	USART_CR1 &= (uint16)(~(0x2000));
	USART_CR1 |= (uint16)0x2000;
	/*清除发送完成中断挂起状态*/
	USART_SR &= (uint16)~0x0040;
	/*接收缓冲区非空中断使能*/
	USART_CR1 &= (uint16)(~(0x0020));
	USART_CR1 |= (uint16)0x0020;
	/*****NVIC配置*****/
	/*优先级分组设置*/
	SCB_AIRCR = (uint32)0x05fa0500;
	/*优先级设置*/
	NVIC_IPR9 |= (uint32)0x0000f000;
	/*USART1中断使能*/
	NVIC_ISER1 = (uint32)0x00000020;
}

/*USART1中断处理函数*/
void USART1_IRQHandler(void){
	uint8 r = 0;
	
	/*判断是否是接收中断*/
	if((USART_SR & (uint32)0x00000020) != 0){
		r = USART_DR;
		USART_DR = r;
		while((USART_SR & (uint32)0x00000040) == 0);
	}
	/*清除发送完成状态标志*/
	USART_SR &= (uint32)~0x00000040;
}
